package presentation.web;

import java.rmi.RemoteException ;

import jaxcent.HtmlButton ;
import jaxcent.HtmlImage ;
import jaxcent.HtmlInputText ;
import jaxcent.HtmlPara ;
import jaxcent.Jaxception ;

import org.jfree.chart.ChartFactory ;
import org.jfree.chart.ChartUtilities ;
import org.jfree.chart.JFreeChart ;
import org.jfree.chart.axis.NumberAxis ;
import org.jfree.chart.axis.NumberTickUnit ;
import org.jfree.chart.plot.PlotOrientation ;
import org.jfree.data.xy.IntervalXYDataset ;
import org.jfree.data.xy.XYSeries ;
import org.jfree.data.xy.XYSeriesCollection ;

import util.Bug ;
import util.Log ;
import util.NotFoundException ;
import util.Statistics ;
import util.Subsystem ;
import domain.user.Privilege ;


/**
 * view forum and user-specific statistics.
 * @author idan
 */
public class StatisticsPage extends MainPage
{

	private HtmlImage globalPostChart ;
	private HtmlInputText usernameInput;
	private HtmlPara errorsPara;
	private HtmlImage globalLoginChart ;
	private HtmlImage userSpecificChart ;

	/**
	 * build statistics page
	 */
	public StatisticsPage()
	{
		super() ;
		try
		{
			if (!this.verifyUserAllowedPage(Privilege.VIEW_STATISTICS))
			{
				return ;
			}

			this.createUserChart() ;
			this.createMessageChart() ;
			this.createUserSpecificChartMaker() ;
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	/**
	 * creates the statistics chart based on the user input.
	 */
	protected void createUserSpecificChart()
	{
		try
		{
			this.errorsPara.setInnerHTML("");
			String username = this.usernameInput.getValue() ;
			//checks if user enter username to become moderator
			if(username.equals(""))
			{
				this.errorsPara.setInnerHTML("Missing username!");
			}
			else
			{
				long memberId = this.getForumLogic().getMemberId(username) ;
				Statistics perUserStatistics = this.getForumLogic().getPostStatisticsForMember(memberId) ;
				this.createChart(perUserStatistics, this.userSpecificChart, "posts per member",
					"day of the month", "amount of posts") ;
				this.userSpecificChart.show() ;
			}
		}
		catch (NotFoundException e)
		{
			try
			{
				this.usernameInput.setValue("");
				this.errorsPara.setInnerHTML("username not found - enter correct username");
				this.userSpecificChart.hide() ;
				Log.getLogger(Subsystem.PRESENTATION_MODEL).info("username  not in system. maybe typed incorrect user") ;
			}
			catch (Jaxception e1)
			{
				this.navigateToErrorPage(e1, this.usernameInput) ;
			}
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.userSpecificChart) ;
		}
	}

	private void createChart(final Statistics data, final HtmlImage element, final String title,
		final String xAxis, final String yAxis)
	{
		try
		{
			XYSeries series = new XYSeries(title) ;
			for (int i = 0 ; i < data.getQuantum() ; i++)
			{
				series.add( i, data.get(i)) ;
			}
			IntervalXYDataset xyDataset = new XYSeriesCollection(series);
			JFreeChart chart = ChartFactory.createXYBarChart(title, xAxis, false, yAxis, xyDataset,
				PlotOrientation.VERTICAL, false, false, false) ;

			// x axis: the range is known in advance
			NumberAxis domain = new NumberAxis(xAxis) ;
			domain.setAutoTickUnitSelection(false) ;
			domain.setRange(0, data.getQuantum()) ;
			chart.getXYPlot().setDomainAxis(domain) ;

			// y axis: the range is only known to start from 0
			NumberAxis range = new NumberAxis(yAxis) ;
			range.setAutoTickUnitSelection(false) ;
			range.setTickUnit(new NumberTickUnit(1)) ;
			chart.getXYPlot().setRangeAxis(range) ;
			chart.getXYPlot().getRangeAxis().setLowerBound(0) ;

			byte[] image = ChartUtilities.encodeAsPNG(chart.createBufferedImage(600, 400)) ;
			element.setSrc(image, "image/png") ;
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null);
		}
	}

	/**
	 * build the post statistics chart.
	 */
	private void createMessageChart()
	{
		try
		{
			this.globalPostChart = new HtmlImage(this, "globalPostChart") ;
			Statistics messages = this.getForumLogic().getPostStatistics() ;
			this.createChart(messages, this.globalPostChart, "Post statistics", "hour of the day", "amount of posts") ;
		}
		catch (RemoteException e)
		{
			throw new Bug("throwing remote exception from the same process as the server.");
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.globalPostChart) ;
		}
	}

	/**
	 * build the login statistics chart.
	 */

	private void createUserChart()
	{
		try
		{
			this.globalLoginChart = new HtmlImage(this, "globalLoginChart") ;
			Statistics users = this.getForumLogic().getUserStatistics() ;
			this.createChart(users, this.globalLoginChart, "Member statistics", "hour of the day", "amount of logins") ;
		}
		catch (RemoteException e)
		{
			throw new Bug("throwing remote exception from the same process as the server.");
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.globalPostChart) ;
		}
	}

	/**
	 * build the user specific statistics chart creation mechanism.
	 */
	private void createUserSpecificChartMaker()
	{
		try
		{
			this.usernameInput = new HtmlInputText(this,"usernameInput");
			this.setErrors();
			this.makeButton();
			this.userSpecificChart = new HtmlImage(this, "userSpecificChart") ;
			this.userSpecificChart.hide() ;
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null) ;
		}
	}

	private void makeButton()
	{
		try
		{
			new HtmlButton(this,"getUserStatistics"){
		        @Override
				protected void onClick() {
		        	StatisticsPage.this.createUserSpecificChart();
		        }
		    };
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, null) ;
		}
	}

	private void setErrors()
	{
		try
		{
			this.errorsPara = new HtmlPara(this,"userStatisticsErrors");
			this.errorsPara.setInnerHTML("");
		}
		catch (Exception e)
		{
			this.navigateToErrorPage(e, this.errorsPara) ;
		}
	}

}
